/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.xd.controller;

import com.xy.biz.base.client.DictClient;
import com.xy.biz.base.domain.req.ListDictItemRequest;
import com.xy.biz.base.domain.resp.ListDictItemResponse;
import com.xy.biz.fd.domain.req.folder.ListFolderRequest;
import com.xy.biz.uc.domain.dto.UserDTO;
import com.xy.biz.uc.domain.enums.UserGroupCodeEnum;
import com.xy.biz.xd.client.DocumentFlowClient;
import com.xy.biz.xd.domain.converter.DocumentFlowConverter;
import com.xy.biz.xd.domain.converter.DocumentFlowHandleUserConverter;
import com.xy.biz.xd.domain.converter.DocumentReleaseConverter;
import com.xy.biz.fd.domain.enums.DocumentDefaultRepositoryEnum;
import com.xy.biz.xd.domain.enums.DocumentFlowBatchTypeEnum;
import com.xy.biz.xd.domain.enums.DocumentFlowExistStatusEnum;
import com.xy.biz.xd.domain.query.DocumentFlowHandleQuery;
import com.xy.biz.xd.domain.query.DocumentFlowQuery;
import com.xy.biz.xd.domain.query.DocumentReleaseQuery;
import com.xy.biz.xd.domain.req.*;
import com.xy.biz.xd.domain.req.documentRelease.ListDocumentReleaseRequest;
import com.xy.biz.xd.domain.resp.*;
import com.xy.biz.xd.service.DocumentFlowHandleService;
import com.xy.biz.xd.service.DocumentFlowNewService;
import com.xy.biz.xd.service.DocumentFlowService;
import com.xy.biz.xd.service.DocumentReleaseService;
import com.xy.lang.domain.KeyValue;
import com.xy.lang.domain.Page;
import com.xy.lang.domain.PageRequest;
import com.xy.lang.domain.Result;
import com.xy.lang.util.ResultUtils;
import com.xy.lang.validation.annotation.Validatable;
import com.xy.tool.context.UserContextHolder;
import com.xy.tool.util.BeanUtilsEx;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;

import static com.xy.biz.xd.domain.bo.DocumentFlowConstants.*;

/**
 * @author zsp
 * @date 2021-1-22
 */
@Api(tags = "文档流程服务")
@Slf4j
@RequestMapping("/api/xd/document_flow")
@RestController
public class DocumentFlowController implements DocumentFlowClient {

    @Autowired
    private DictClient dictClient;
    @Autowired
    private DocumentFlowService documentFlowService;
    @Autowired
    private DocumentReleaseService documentReleaseService;
    @Autowired
    private DocumentFlowHandleService documentFlowHandleService;


    @Validatable
    @PostMapping(value = "/delete")
    public Result<?> deleteDocumentFlow(@RequestBody GetDocumentFlowRequest request) {
        documentFlowService.deleteDocumentFlow(request.getDocumentFlowId());
        return Result.success();
    }

    @Validatable
    @PostMapping(value = "/get")
    @Override
    public Result<GetDocumentFlowResponse> getDocumentFlow(@RequestBody GetDocumentFlowRequest request) {
        return Result.success(DocumentFlowConverter.toResponse(documentFlowService.getDocumentFlow(request.getDocumentFlowId())));
    }

    @PostMapping(value = "/list_by_ids")
    @Override
    public Result<List<GetDocumentFlowResponse>> listDocumentFlowById(@RequestBody Collection<Long> collection) {
        return Result.success(DocumentFlowConverter.toResponse(documentFlowService.listDocumentFlowById(collection)));
    }

    @PostMapping(value = "/list")
    @Override
    public Result<List<GetDocumentFlowResponse>> listDocumentFlow(@RequestBody ListDocumentFlowRequest request) {
        return Result.success(DocumentFlowConverter.toResponse(documentFlowService.listDocumentFlow(DocumentFlowConverter.toQuery(request))));
    }

    @PostMapping(value = "/list2")
    public Result<List<GetDocumentFlowResponse>> listDocumentFlow2(@RequestBody ListDocumentFlowRequest request) {
        return Result.success(DocumentFlowConverter.toResponse(documentFlowService.listDocumentFlow2(DocumentFlowConverter.toQuery(request))));
    }

    @PostMapping(value = "/count")
    @Override
    public Result<Integer> countDocumentFlow(@RequestBody ListDocumentFlowRequest request) {
        return Result.success(documentFlowService.countDocumentFlow(DocumentFlowConverter.toQuery(request)));
    }

    @PostMapping(value = "/page")
    @Override
    public Result<Page<GetDocumentFlowResponse>> pageDocumentFlow(@RequestBody ListDocumentFlowRequest request) {
        DocumentFlowQuery query = DocumentFlowConverter.toQuery(request);
        List<GetDocumentFlowResponse> list = DocumentFlowConverter.toResponse(documentFlowService.listDocumentFlow(query));
        int count = documentFlowService.countDocumentFlow(query);
        return Result.success(new Page<>(list, count));
    }

    @ApiOperation("流程列表-待办事项")
    @PostMapping(value = "/page_todo")
    public Result<Page<GetDocumentFlowResponse>> pageTodoDocumentFlow(@RequestBody PageRequest request) {
        DocumentFlowQuery query = DocumentFlowConverter.toQuery(request);
        return Result.success(documentFlowService.searchDocumentFlowTodo(query));
    }

    @ApiOperation("流程列表-待办事项-数量统计")
    @PostMapping(value = "/page_todo_count")
    public Result<Integer> pageTodoDocumentFlowCount() {
        return Result.success(documentFlowService.pageTodoDocumentFlowCount());
    }

    @ApiOperation("流程列表-我发起的")
    @PostMapping(value = "/page_start")
    public Result<Page<GetDocumentFlowResponse>> pageStartDocumentFlow(@RequestBody ListDocumentFlowRequest request) {
        DocumentFlowQuery query = DocumentFlowConverter.toQuery(request);
        query.setCreateUserId(UserContextHolder.getUserId());
        List<GetDocumentFlowResponse> list = DocumentFlowConverter.toResponse(documentFlowService.listDocumentFlow(query));
        int count = documentFlowService.countDocumentFlow(query);
        buildGetDocumentFlowResponse(list);
        return Result.success(new Page<>(list, count));
    }

    @ApiOperation("流程列表-我参与的")
    @PostMapping(value = "/page_participant")
    public Result<Page<GetDocumentFlowResponse>> pageParticipantDocumentFlow(@RequestBody ListParticipantDocumentFlowRequest request) {
        DocumentFlowHandleQuery query = new DocumentFlowHandleQuery(request.getPageIndex(), request.getPageSize());
        BeanUtilsEx.copyProperties(request, query);
        query.setHandleUserId(UserContextHolder.getUserId());
        int count = documentFlowHandleService.countDocumentFlowHandle(query);
        if (count == 0) {
            return Result.success(new Page<>(null, count));
        }
        query.setOffset(request.getPageIndex());
        query.setRows(request.getPageSize());
        List<GetDocumentFlowResponse> list = documentFlowHandleService.listDocumentFlowHandle(query);
        buildGetDocumentFlowResponse(list);
        return Result.success(new Page<>(list, count));
    }

    @ApiOperation("查看发行文档签收情况")
    @Validatable
    @PostMapping(value = "/release_check")
    public Result<?> releaseCheck(@RequestBody GetDocumentReleaseCheckStatusRequest request) {
        return documentReleaseService.DocumentReleaseCheck(request);
    }

    @ApiOperation("查看包含培训的流程信息")
    @Validatable
    @PostMapping(value = "/get_train_by_document_flow")
    public Result<?> getTrainByDocumentFlow(@RequestBody GetDocumentReleaseCheckStatusRequest request) {
        return documentReleaseService.getTrainByDocumentFlow(request.getDocumentFlowId());
    }

    @ApiOperation("流程列表-签收处理")
    @PostMapping(value = "/sign_in_processing")
    public Result<Page<GetDocumentReleaseResponse>> signInProcessing(@RequestBody ListDocumentReleaseRequest request) {
        DocumentReleaseQuery query = DocumentReleaseConverter.toQuery(request);
        query.setReceiveUserId(UserContextHolder.getUserId());
        query.setReceiveUserGroupId(UserContextHolder.getUserGroupId());
        List<GetDocumentReleaseResponse> list = DocumentReleaseConverter.toResponse(documentReleaseService.signInProcessing(query));
        int count = documentReleaseService.countDocumentRelease(query);
        buildGetDocumentReleaseResponse(list);
        return Result.success(new Page<>(list, count));
    }

    @ApiOperation("流程列表-生效处理")
    @PostMapping(value = "/effective_processing")
    public Result<Page<GetDocumentReleaseResponse>> effectiveProcessing(@RequestBody ListDocumentReleaseRequest request) {
        DocumentReleaseQuery query = DocumentReleaseConverter.toQuery(request);
        List<GetDocumentReleaseResponse> list = DocumentReleaseConverter.toResponse(documentReleaseService.effectiveProcessing(query));
        int count = documentReleaseService.countAllDocumentRelease(query);
        buildGetDocumentReleaseResponse(list);
        return Result.success(new Page<>(list, count));
    }

    @ApiOperation("流程列表-签收功能")
    @PostMapping(value = "/sign_for")
    public Result<?> sign_for_document(@RequestBody GetDocumentReleaseRequest request) {
        return documentReleaseService.signForDocument(request.getDocumentReleaseId());
    }

    @ApiOperation("流程列表-批量签收功能")
    @PostMapping(value = "/sign_for_batch")
    public Result<?> signForDocumentBatch(@RequestBody SignDocumentReleaseRequest request) {
        return documentReleaseService.signForDocumentBatch(request);
    }

    /**
     * 发行知识库
     * @param
     * @return
     */
    @ApiOperation("发行知识库")
    @PostMapping(value = "/get_release")
    public Result<?> getRelease(@RequestBody ListFolderRequest request) {
        return documentReleaseService.getRelease(request);
    }

    /**
     * 现行文件查看文件信息
     * @param
     * @return
     */
    @ApiOperation("现行文件查看文件信息")
    @PostMapping(value = "/get_document_info_of_release")
    public Result<DocumentAllInfoResponse> getDocumentInfoOfRelease(@RequestBody GetDocumentFlowRequest request) {
        return documentFlowService.getDocumentAllInfo(request);
    }

    /**
     * 文档生效
     * @param
     * @return
     */
    @ApiOperation("文档生效开关打开")
    @PostMapping(value = "/take_effect")
    public Result<?> takeEffect(@RequestBody GetDocumentReleaseRequest request) {
        DocumentReleaseQuery query = DocumentReleaseQuery.builder().documentReleaseId(request.getDocumentReleaseId()).build();
        return documentReleaseService.takeEffectDocumentRelease(query);
    }

    /**
     * 文档失效
     * @param
     * @return
     */
    @ApiOperation("文档生效开关关闭")
    @PostMapping(value = "/lose_effect")
    public Result<?> loseEffect(@RequestBody GetDocumentReleaseRequest request) {
        DocumentReleaseQuery query = DocumentReleaseQuery.builder().documentReleaseId(request.getDocumentReleaseId()).build();
        return documentReleaseService.loseEffectDocumentRelease(query);
    }

    @ApiOperation("工具方法，重新选择流程文件发放部门")
    @PostMapping(value = "/reallocate")
    public Result<?> reallocate(@RequestBody Collection<String> collection) {
        return documentReleaseService.reallocate(collection);
    }

    @ApiOperation("文件增加发放对象")
    @PostMapping(value = "/add_receive")
    public Result<?> addDocumentReleaseReceive(@RequestBody SaveDocumentReleaseReceiveRequest request) {
        return documentReleaseService.addDocumentReleaseReceive(request);
    }

    /**
     * 通过文件属性查找文件
     * @param
     * @return
     */
    @ApiOperation("通过属性查找发行的文件")
    @PostMapping(value = "/get_document_list_by_type")
    public Result<?> getDocumentListByType(@RequestBody ListDocumentByTypeRequest request) {
        return documentReleaseService.getDocumentListByType(request);
    }

    @ApiOperation("查找当前是否有存在的流程")
    @Validatable
    @PostMapping(value = "/get_flow_exist")
    public Result<?> getFlowExist(@RequestBody GetDocumentFlowExistRequest request) {
        return documentFlowService.getFlowExist(request);
    }

    @ApiOperation("添加后续流程节点处理人")
    @Validatable
    @PostMapping(value = "/save_handle_user")
    public Result<?> saveHandleUser(@RequestBody Collection<SaveDocumentFlowHandleUserRequest> request) {
        return documentFlowService.saveHandleUser(DocumentFlowHandleUserConverter.toBO(request));
    }

    @ApiOperation("获取后续流程节点处理人")
    @PostMapping(value = "/list_handle_user")
    public Result<List<GetDocumentFlowHandleUserResponse>> listHandleUser(@RequestBody ListDocumentFlowHandleUserRequest request) {
        return documentFlowService.listHandleUser(DocumentFlowHandleUserConverter.toQuery(request));
    }

    @ApiOperation("文件剔除发放对象")
    @Validatable
    @PostMapping(value = "/delete_receive")
    public Result<?> deleteDocumentReleaseReceive(@RequestBody SaveDocumentReleaseReceiveRequest request) {
        return documentReleaseService.deleteDocumentReleaseReceive(request);
    }

    @ApiOperation("文件增加发放对象（批量）")
    @Validatable
    @PostMapping(value = "/add_receive_list")
    public Result<?> addDocumentReleaseReceiveList(@RequestBody SaveDocumentReleaseReceiveListRequest request) {
        return documentReleaseService.addDocumentReleaseReceiveList(request);
    }

    @ApiOperation("获取流程中等待任务的人")
    @Validatable
    @PostMapping(value = "/list_assignee")
    public Result<List<UserDTO>> listAssignee(@RequestBody GetDocumentFlowRequest request) {
        return documentFlowService.listAssignee(request.getDocumentFlowId());
    }

    private Map<Integer, String> getFlowTypeMap() {
        List<ListDictItemResponse> listDictItemResponseList
                = ResultUtils.get(dictClient.listDictItem(ListDictItemRequest.builder().dictGroupCode("flow_type").build()));
        Map<Integer, String> flowTypeMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(listDictItemResponseList)) {
            try {
                listDictItemResponseList.forEach(e -> flowTypeMap.put(Integer.parseInt(e.getDictCode()), e.getDictValue()));
            } catch (Exception e) {
                log.error("流程类型编码转换错误", e);
            }
        }
        return flowTypeMap;
    }

    private void buildGetDocumentFlowResponse(List<GetDocumentFlowResponse> list) {
        if (!CollectionUtils.isEmpty(list)) {
            Map<Integer, String> flowTypeMap = getFlowTypeMap();
            for (GetDocumentFlowResponse getDocumentFlowResponse : list) {
                getDocumentFlowResponse.setFlowTypeName(flowTypeMap.get(getDocumentFlowResponse.getFlowType()));
                getDocumentFlowResponse.setPhaseName(getPhaseName(getDocumentFlowResponse.getFlowType(), getDocumentFlowResponse.getPhase()));
                if (Objects.equals(URGENT_NORMAL, getDocumentFlowResponse.getUrgent())) {
                    getDocumentFlowResponse.setUrgentName("正常");
                } else if (Objects.equals(URGENT_URGENT, getDocumentFlowResponse.getUrgent())) {
                    getDocumentFlowResponse.setUrgentName("紧急");
                } else {
                    getDocumentFlowResponse.setUrgentName(getDocumentFlowResponse.getUrgent());
                }
            }
        }
    }

    private void buildGetDocumentReleaseResponse(List<GetDocumentReleaseResponse> list) {
        if (!CollectionUtils.isEmpty(list)) {
            Map<Integer, String> flowTypeMap = getFlowTypeMap();
            for (GetDocumentReleaseResponse getDocumentReleaseResponse : list) {
                getDocumentReleaseResponse.setFlowTypeName(flowTypeMap.get(getDocumentReleaseResponse.getFlowType()));
            }
        }
    }

    @ApiOperation("获取流程字典信息")
    @GetMapping(value = "/list_pre_options")
    public Result<Map<String, List>> listPreOptions() {
        Map<String, List> map = new HashMap<>(2);
        map.put("phase", listDefaultRepository());
        map.put("userGroupCode", listUserGroupCode());
        map.put("flowExistStatus", listUserGroupCode1());
        List<ListDictItemResponse> dictList = dictClient.listDictItem(
                ListDictItemRequest.builder().pageSize(1000).dictGroupCodes(
                        Collections.singletonList("document_category")).build()).getData();
        if (!CollectionUtils.isEmpty(dictList)) {
            List<KeyValue<String, String>> documentCategoryList = new ArrayList<>();
            dictList.forEach(e -> {
                if ("document_category".equals(e.getDictGroupCode())) {
                    documentCategoryList.add(new KeyValue<>(e.getDictCode(), e.getDictValue()));
                }
            });
            map.put("documentCategoryList", documentCategoryList);
        }
        return Result.success(map);
    }

    private List<KeyValue<Long, String>> listDefaultRepository() {
        DocumentDefaultRepositoryEnum[] enums = DocumentDefaultRepositoryEnum.values();
        List<KeyValue<Long, String>> list = new ArrayList<>();
        for (DocumentDefaultRepositoryEnum e : enums) {
            list.add(e.toKeyValue());
        }
        return list;
    }

    private List<KeyValue<String, String>> listUserGroupCode() {
        UserGroupCodeEnum[] enums = UserGroupCodeEnum.values();
        List<KeyValue<String, String>> list = new ArrayList<>();
        for (UserGroupCodeEnum e : enums) {
            list.add(e.toKeyValue());
        }
        return list;
    }

    private List<KeyValue<Integer, String>> listUserGroupCode1() {
        DocumentFlowExistStatusEnum[] enums = DocumentFlowExistStatusEnum.values();
        List<KeyValue<Integer, String>> list = new ArrayList<>();
        for (DocumentFlowExistStatusEnum e : enums) {
            list.add(e.toKeyValue());
        }
        return list;
    }

}
